package com.fm.mediasoup;

import android.content.Context;

import com.fm.mediasoup.callback.TrackCallback;
import com.fm.mediasoup.sdpTransform.Sdp;
import com.fm.mediasoup.sdpTransform.SdpTransform;
import com.fm.mediasoup.callback.CallbackMediaStream;
import com.fm.mediasoup.callback.CallbackSdp;
import com.fm.mediasoup.json.HeaderExtension;
import com.fm.mediasoup.json.IceParameter;
import com.fm.mediasoup.json.RtpParameters;
import com.fm.mediasoup.sdp.Candidate;
import com.fm.mediasoup.sdp.Connection;
import com.fm.mediasoup.sdp.Fingerprint;
import com.fm.mediasoup.sdp.Media;
import com.fm.mediasoup.sdp.MsidSemantic;
import com.fm.mediasoup.sdp.Origin;
import com.fm.mediasoup.sdp.Timing;
import com.fm.mediasoup.util.MessageUtil;

import org.webrtc.EglBase;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.VideoSink;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Transport {

    private final static String TAG = Transport.class.getSimpleName();

    public boolean isConnect() {
        return isConnect;
    }

    public void setConnect(boolean connect) {
        isConnect = connect;
    }

    private boolean isConnect = false;

    public List<Fingerprint> getFingerprint() {
        return fingerprint;
    }


    public Candidate[] getCandidates() {
        return candidates;
    }

    /**
     * sdp 密钥交互
     */
    private List<Fingerprint> fingerprint;

    /**
     * 候选者列表
     */
    private List<Candidate> candidateList;

    private Candidate[] candidates;

    /**
     * 数据流回调
     */
    private CallbackMediaStream callbackMediaStream;

    /**
     * sdp 回调
     */
    private CallbackSdp callbackSdp;

    /**
     * webrtc 数据设置
     */
    private Webrtc webrtc;

    private EglBase.Context eglBaseContext;

    public String getId() {
        return id;
    }

    /**
     * 消费者map 列表
     */
    public HashMap<String, Consumer> consumerHashMap = new HashMap<>();


    public IceParameter getIceParameter() {
        return iceParameter;
    }

    private IceParameter iceParameter;

    private String id;

    public Transport(String id, Context context, EglBase.Context eglBaseContext) {
        this(id, context, eglBaseContext, null, null, null);
    }

    public Transport(String id, Context context, EglBase.Context eglBaseContext, List<Fingerprint> fingerprint, List<Candidate> candidate, IceParameter iceParameter) {
        this.id = id;
        this.webrtc = new Webrtc(context, eglBaseContext);
        this.fingerprint = fingerprint;
        this.candidateList = candidate;
        this.iceParameter = iceParameter;
        this.candidates = new Candidate[this.candidateList.size()];
        this.candidateList.toArray(this.candidates);
    }

    /**
     * 设置接收数据流回调
     * @param callbackMediaStream
     */
    public void setCallbackMediaStream(CallbackMediaStream callbackMediaStream){
        this.callbackMediaStream = callbackMediaStream;
        this.webrtc.setCallbackMediaStream(callbackMediaStream);
    }


    /**
     * 设置 sdp 信息回调
     * @param callbackSdp
     */
    public void setCallbackSdp(CallbackSdp callbackSdp) {
        this.callbackSdp = callbackSdp;
        this.webrtc.setCallbackSdp(this.callbackSdp);
    }

    /**
     * 消费者
     * @param id
     * @param rtpParameters
     * @return
     */
    public Consumer consumer(String id, RtpParameters rtpParameters){
        Consumer consumer = new Consumer(id, rtpParameters);
        consumerHashMap.put(id, consumer);
        Sdp consumeSdp = createOfferSdp();
        String offer = SdpTransform.write(MessageUtil.toJson(consumeSdp));
        this.webrtc.setOfferDescription(offer);
        this.webrtc.createAnswer();
        return consumer;
    }

    /**
     * 生产者
     * @param video
     * @param audio
     * @param trackCallback
     * @param surfaceTextureHelper
     * @return
     */
    public Producer producer(boolean video, boolean audio, TrackCallback trackCallback, SurfaceTextureHelper surfaceTextureHelper){
        Producer producer = new Producer();
        this.webrtc.setTrackCallback(trackCallback);
        if (video) {
            this.webrtc.addVideoTrack();
            this.webrtc.startVideoCapturer(surfaceTextureHelper);
        }
        if (audio)
            this.webrtc.addAudioTrack();
        this.webrtc.createOffer();
        producer.setWebrtc(webrtc);
        return producer;
    }

    public void setAnswerDescription(String sdp){
        this.webrtc.setAnswerDescription(sdp);
    }


    /**
     *  接收 数据
     * @return
     */
    public Sdp createOfferSdp(){
        List<Media> mediaList = new ArrayList<>();
        for (Map.Entry<String,Consumer> rtpParametersEntry :this.consumerHashMap.entrySet()) {
            RtpParameters rtpParameters = rtpParametersEntry.getValue().getRtpParameters();
            String id = rtpParametersEntry.getKey();
            Media media = new Media.Builder().
                    setType(rtpParameters.kind).
                    setRtp(rtpParameters.parseRtp()).
                    setFmtp(rtpParameters.parseFmtp()).
                    setRtcpFb(rtpParameters.parseRtcpFb()).
                    setExt(rtpParameters.parseExt()).
                    setPort(9).
                    setProtocol("UDP/TLS/RTP/SAVPF").
                    setMid(rtpParameters.mid).
                    setDirection("sendonly").
                    setIceUfrag(this.getIceParameter().getUsernameFragment()).
                    setIcePwd(this.getIceParameter().getPassword()).
                    setCandidates(candidates).
                    setMsid(rtpParameters.streamId + " " + id).
                    setSsrcGroups(rtpParameters.parseSSrcGroups()).
                    setSsrcs(rtpParameters.parseSsrcs()).
                    setSetup("actpass").
                    setIceOptions("renomination").
                    setConnection(new Connection.Builder().setIp("127.0.0.1").setVersion("4").build()).
                    setRtcpMux("rtcp-mux").
                    setRtcpRsize("rtcp-rsize").
                    build();
            mediaList.add(media);
        }

        Collections.sort(mediaList, new Comparator<Media>()
        {
            public int compare(Media a1, Media a2)
            {
                return Integer.valueOf(a1.mid) - Integer.valueOf(a2.mid);
            }
        });


        Media[] medias = new Media[mediaList.size()];
        mediaList.toArray(medias);
        return new Sdp.Builder().
                setName("-").
                setIcelite("ice-lite").
                setMsidSemantic(new MsidSemantic.Builder().setSemantic("WMS").setToken("*").build()).
                setOrigin(new Origin.Builder().setAddress("0.0.0.0").setIpVer(4).setNetType("IN").setSessionId("10000").setUsername("fm").setSessionVersion(2).build()).
                setFingerprint(this.getFingerprint().stream().findFirst().get()).
                setMedia(medias).
                setGroups().
                setTiming(new Timing.Builder().setStart(0).setStop(0).build()).build();
    }

    /**
     * producer 设置服务端 answer
     * @param offerSdp
     * @return
     */
    public Sdp createAnswerSdp(Sdp offerSdp, HeaderExtension[] headerExtensions) {
        Fingerprint fingerprint = this.getFingerprint().stream().findFirst().get();

        List<Media> mediaList = new ArrayList<>();
        for (Media media: offerSdp.media) {
            mediaList.add(new Media.Builder().
                    setRtp(media.rtp). //优先设置
                    setType(media.type).
                    setRtcpFb(media.rtcpFb).
                    setFmtp(media.fmtp).
                    setExt(media.ext, headerExtensions).
                    setIceUfrag(this.getIceParameter().getUsernameFragment()).
                    setIcePwd(this.getIceParameter().getPassword()).
                    setFingerprint(fingerprint).
                    setCandidates(this.getCandidates()).
                    setMid(media.mid).
                    setDirection("recvonly").
                    setPort(media.port).
                    setProtocol(media.protocol).
                    setSetup("passive").
                    setIceOptions("renomination").
                    setConnection(new Connection.Builder().setIp("127.0.0.1").setVersion("4").build()).
                    setRtcpMux("rtcp-mux").
                    setRtcpRsize("rtcp-rsize").build());
        }

        Media[] mediaArray = new Media[mediaList.size()];
        mediaList.toArray(mediaArray);

        return  new Sdp.Builder().
                setName("-").
                setIcelite("ice-lite").
                setMedia(mediaArray).
                setMsidSemantic(new MsidSemantic.Builder().setSemantic("WMS").setToken("*").build()).
                setOrigin(new Origin.Builder().setAddress("127.0.0.1").setIpVer(4).setNetType("IN").setSessionId("10000").setUsername("fm").setSessionVersion(2).build()).
                setTiming(new Timing.Builder().setStart(0).setStop(0).build()).
                setGroups().
                build();
    }


    public void release(){
        try {
            if (this.webrtc != null) {
                this.webrtc.release();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

    }


}
